<!-- 新建课程页面 -->
<template>
  <edit-card
    :title="cardTitle"
    :type="cardType ? 'add' : 'edit'"
    :loading="loading || addCourseFormLoading || editCourseFormLoading"
    @confirm="handleConfirm()"
  >
    <a-form
      ref="formRef"
      :model="formState"
      :rules="rules"
      :label-col="{ style: { width: '120px' } }"
      style="width: 616px"
      label-align="left"
    >
      <a-form-item label="课程名称" name="name">
        <a-input v-model:value="formState.name" v-trim placeholder="请输入课程名称" class="w440" :maxlength="200" />
      </a-form-item>

      <a-form-item label="课程分类" name="categories">
        <div class="w440">
          <a-select
            v-model:value="formState.categories"
            mode="multiple"
            :show-search="false"
            style="width: 100%"
            placeholder="请选择课程分类"
            :get-popup-container="getPopupContainer"
            max-tag-count="responsive"
            class="w440"
            show-arrow
            :options="classifyOptions"
            :field-names="{ label: 'v', value: 'id' }"
            @change="handleChange"
          />
        </div>
      </a-form-item>

      <a-form-item label="课程级别" name="levels">
        <div class="w440">
          <a-select
            v-model:value="formState.levels"
            mode="multiple"
            style="width: 100%"
            placeholder="请选择课程级别"
            max-tag-count="responsive"
            :get-popup-container="getPopupContainer"
            show-arrow
            :show-search="false"
            :options="rankOptions"
            :field-names="{ label: 'v', value: 'id' }"
            @change="handleChange"
          />
        </div>
      </a-form-item>

      <a-form-item label="预览图" name="previewUrl">
        <image-upload v-model:image-url="previewUrls" v-model:image-name="formState.previewUrl" class="w312" :max-file-size="2">
          <template #info>
            <div class="upload-image-info">
              <div>
                <p>大小不超过2M</p>
                <p>仅支持jpg、jpeg、png格式</p>
              </div>
            </div>
          </template>
        </image-upload>
      </a-form-item>

      <a-form-item label="描述" :colon="false">
        <a-textarea v-model:value="formState.description" v-trim show-count :maxlength="200" :rows="4" class="w440" />
      </a-form-item>

      <a-form-item label="上传文件" name="fileList" class="required" :colon="false">
        <a-checkbox-group :value="formState.checkoutList" name="checkboxGroup" :options="plainOptions" @change="checkoutChange" />
      </a-form-item>

      <a-form-item v-if="showVideo" name="videoUrls" class="upload-item">
        <div class="upload-card">
          <div class="upload-header">
            <div class="iconfont icon-movie-2-line icon-class"></div>
            <div class="upload-header-title">上传视频</div>
          </div>
          <div class="upload-box">
            <file-upload
              ref="videoUploadRef"
              v-model:file-url="formState.videoUrls"
              :max-file-size="-1"
              upload-text="视频"
              upload-tip="仅支持mp4格式"
            />
          </div>
        </div>
      </a-form-item>

      <a-form-item v-if="showText" name="docUrls" class="upload-item">
        <div class="upload-card">
          <div class="upload-header">
            <i class="iconfont icon-file-paper-2-line icon-class"></i>
            <div class="upload-header-title">上传文档</div>
          </div>
          <div class="upload-box">
            <file-upload
              ref="docUploadRef"
              v-model:file-url="formState.docUrls"
              :max-file-size="-1"
              upload-text="文档"
              accept="ppt,pptx,pdf,doc,docx"
              upload-tip="仅支持ppt、pptx、pdf、doc、docx格式"
            />
          </div>
        </div>
      </a-form-item>

      <a-form-item v-if="showAttachments" name="attachments" class="upload-item">
        <div class="upload-card">
          <div class="upload-header">
            <i class="iconfont icon-attachment-line icon-class"></i>
            <div class="upload-header-title">上传附件</div>
          </div>
          <div class="upload-box">
            <file-upload
              ref="attachmentsUploadRef"
              v-model:file-url="formState.attachments"
              :max-file-size="-1"
              upload-text="附件"
              accept="zip"
              upload-tip="仅支持zip格式"
            />
          </div>
        </div>
      </a-form-item>
    </a-form>
  </edit-card>
</template>

<script lang="ts" setup>
  import { type FormInstance, message } from 'ant-design-vue'
  import type { Rule } from 'ant-design-vue/es/form'
  import { cloneDeep, debounce } from 'g6-fn'
  import { computed, onMounted, reactive, ref } from 'vue'
  import { useRequest } from 'vue-request'
  import { useRoute, useRouter } from 'vue-router'

  import ImageUpload from '@/components/ImageUpload/index.vue'
  import { courseAdminApi, tagManageApi } from '@/services/api'
  import { countStrToBit, getDifference, regex, validateBitLen, validateDirName } from '@/utils'

  import { DictionaryVOResponse, FileListType, FormState } from '../types'
  import FileUpload from './components/FileUpload.vue'
  const router = useRouter()
  const route = useRoute()

  const cardType = route.query.type === 'add'
  const detailData = ref<FormState>()

  const cardTitle = computed(() => {
    return cardType ? '新建课程' : `编辑课程（${detailData.value?.name || ''}）`
  })
  const formRef = ref<FormInstance>()
  const formState = reactive<FormState>({
    attachments: [],
    categories: [],
    description: null,
    docUrls: [],
    levels: [],
    name: '',
    previewUrl: '',
    videoUrls: [],
    checkoutList: ['1', '2', '3'],
    id: ''
  })

  const previewUrls = ref()
  const videoUploadRef = ref<InstanceType<typeof FileUpload>>()
  const docUploadRef = ref<InstanceType<typeof FileUpload>>()
  const attachmentsUploadRef = ref<InstanceType<typeof FileUpload>>()
  const rankOptions = ref<DictionaryVOResponse[]>([])
  const classifyOptions = ref<DictionaryVOResponse[]>([])

  // 获取标签
  const { runAsync: getDataLabel, loading } = useRequest<ResponseData<DictionaryVOResponse[]>>(tagManageApi.list, {
    onSuccess: res => {
      for (let item of res.data) {
        if (item.type === 'course_level') {
          rankOptions.value.push(item)
        } else {
          classifyOptions.value.push(item)
        }
      }
    }
  })

  const handleChange = () => {
    console.log(formState)
  }

  // 自定义规则
  // 视频规则
  const checkVideo = async () => {
    let videoIndex = formState.checkoutList?.includes('1')
    let videoUrlsLength = formState.videoUrls.length === 0

    // 判断是否存在有错误的
    let successfulFileList = formState.videoUrls?.filter(item => item.status === 'successful')
    // if ((videoIndex && videoUrlsLength) || fileStatus) {
    if ((videoIndex && videoUrlsLength) || successfulFileList.length === 0) {
      return Promise.reject('请上传文件')
    } else {
      // 判断文件的字节数
      for (let item of formState.videoUrls) {
        if (countStrToBit(item.fileName) > 200) {
          return Promise.reject('名称不可超过200字节')
        }
      }
    }
    return Promise.resolve()
  }

  //文档规则
  const checkDoc = () => {
    let docIndex = formState.checkoutList?.includes('2')
    let docUrlLength = formState.docUrls?.length === 0
    let successfulFileList = formState.docUrls?.filter(item => item.status === 'successful')
    if ((docIndex && docUrlLength) || successfulFileList.length === 0) {
      return Promise.reject('请上传文件')
    } else {
      // 判断文件的字节数
      for (let item of formState.docUrls) {
        if (countStrToBit(item.fileName) > 200) {
          return Promise.reject('名称不可超过200字节')
        }
      }
    }
    return Promise.resolve()
  }

  // 附件规则
  const checkAttachments = () => {
    let attachmentsIndex = formState.checkoutList?.includes('3')
    let attachmentsLength = formState.attachments?.length === 0
    let successfulFileList = formState.attachments?.filter(item => item.status === 'successful')
    if ((attachmentsIndex && attachmentsLength) || successfulFileList.length === 0) {
      return Promise.reject('请上传文件')
    } else {
      // 判断文件的字节数
      for (let item of formState.attachments) {
        if (countStrToBit(item.fileName) > 200) {
          return Promise.reject('名称不可超过200字节')
        }
      }
    }
    return Promise.resolve()
  }

  // 规则验证
  const rules: Record<string, Rule[]> = {
    name: [
      { required: true, trigger: 'change', message: '请输入课程名称' },
      { validator: validateDirName() },
      { validator: validateBitLen(200), trigger: 'change' }
    ],
    categories: [{ required: true, message: '请选择课程分类' }],
    levels: [{ required: true, message: '请选择课程级别' }],
    dataGroupName: [
      { required: true, message: '请输入模型库名称' },
      {
        pattern: regex.basicName,
        message: '仅支持中英文、数字、横线、下划线、括号、小数点'
      }
    ],
    previewUrl: [{ required: true, message: '请选择图片' }],
    videoUrls: [{ validator: checkVideo }],
    docUrls: [{ validator: checkDoc }],
    attachments: [{ validator: checkAttachments }]
  }

  const plainOptions = [
    { label: '视频', value: '1' },
    { label: '文档', value: '2' },
    { label: '附件', value: '3' }
  ]

  // 显示上传组件
  const showVideo = computed(() => formState.checkoutList?.includes('1'))
  const showText = computed(() => formState.checkoutList?.includes('2'))
  const showAttachments = computed(() => formState.checkoutList?.includes('3'))

  // checkout组件change时不改变当前的选择
  const checkoutChange = (e: string[] | any[]) => {
    // if (formState.checkoutList?.length === 1 && e.length === 0) {
    const isFlag = formState.checkoutList?.length === 1 && e.length === 0
    if (isFlag) {
      return
    }
    const bad = getDifference(formState.checkoutList, e)
    console.log(bad, 'e')
    formState.checkoutList = e
    if (bad.length === 0) {
      return
    }
    if (bad[0] === '1') {
      formState.videoUrls = []
    } else if (bad[0] === '2') {
      formState.docUrls = []
    } else if (bad[0] === '3') {
      formState.attachments = []
    }
  }

  // 新增
  const { loading: addCourseFormLoading, runAsync: addCourseForm } = useRequest<ResponseData<object>>(courseAdminApi.addForm, {
    onSuccess: () => {
      router.back()
      message.success('操作成功')
    }
  })

  // 修改
  const { loading: editCourseFormLoading, runAsync: editCourseForm } = useRequest<ResponseData<object>>(courseAdminApi.editForm, {
    onSuccess: () => {
      router.back()
      message.success('操作成功')
    }
  })

  // 通过id查询详情，回显
  const { runAsync: detailsCourseForm } = useRequest<ResponseData<FormState>>(courseAdminApi.courseDetails(route.query.id), {
    onSuccess: res => {
      detailData.value = res.data
      formState.categories = []
      formState.levels = []
      formState.name = res.data.name || ''
      // 获取课程类别
      res.data.categories.forEach((item: any) => {
        classifyOptions.value.forEach((el: DictionaryVOResponse) => {
          if (el.id === item.labelId) {
            formState.categories.push(item.labelId)
          }
        })
      })

      // 课程级别
      res.data.levels.map((item: any) => {
        rankOptions.value.forEach((el: DictionaryVOResponse) => {
          if (el.id === item.labelId) {
            formState.levels.push(item.labelId)
          }
        })
      })
      // 图片
      formState.previewUrl = res.data.previewUrl
      previewUrls.value = res.data.previewFileUrl
      // 描述
      formState.description = res.data.description || ''

      // 视频
      formState.videoUrls = res.data.videoUrls?.map(item => {
        return {
          ...item,
          status: 'successful'
        }
      })
      // 文档
      formState.docUrls = res.data.docUrls?.map(item => {
        return {
          ...item,
          status: 'successful'
        }
      })
      // 附件
      formState.attachments = res.data.attachments?.map(item => {
        return {
          ...item,
          status: 'successful'
        }
      })

      // 判断存在哪些文件
      FileLength(res.data)
    },
    onError: error => {
      console.log(error)
    }
  })

  const FileLength = (res: FormState) => {
    if (res.videoUrls.length <= 0) {
      formState.checkoutList = formState.checkoutList.filter(item => item !== '1')
    }
    if (res.docUrls.length <= 0) {
      formState.checkoutList = formState.checkoutList.filter(item => item !== '2')
    }
    if (res.attachments.length <= 0) {
      formState.checkoutList = formState.checkoutList.filter(item => item !== '3')
    }
  }

  // 格式化请求参数
  const formatParam = async () => {
    let obj = cloneDeep(formState)
    if (obj.checkoutList.includes('1')) {
      obj.videoUrls = (obj.videoUrls as any[])
        ?.filter(item => item.status === 'successful')
        ?.map((item: FileListType) => {
          return {
            id: item.id,
            size: item.size,
            fileName: item.name ? item.name : item.fileName,
            url: item.url,
            videoDuration: item.videoDuration
          }
        })
    } else {
      obj.videoUrls = []
    }

    if (obj.checkoutList.includes('2')) {
      obj.docUrls = (obj.docUrls as any[])
        ?.filter(item => item.status === 'successful')
        ?.map((item: FileListType) => {
          return {
            id: item.id,
            size: item.size,
            fileName: item.name ? item.name : item.fileName,
            url: item.url
          }
        })
    } else {
      obj.docUrls = []
    }

    if (obj.checkoutList.includes('3')) {
      obj.attachments = (obj.attachments as any[])
        ?.filter(item => item.status === 'successful')
        ?.map((item: FileListType) => {
          return {
            id: item.id,
            size: item.size,
            fileName: item.name ? item.name : item.fileName,
            url: item.url
          }
        })
    } else {
      obj.attachments = []
    }

    obj.levels = obj.levels?.map((item: string) => {
      return {
        labelId: item
      }
    })
    obj.categories = obj.categories?.map((item: string) => {
      return {
        labelId: item
      }
    })

    delete obj['checkoutList']

    obj['id'] = route.query.id ? route.query.id : ''

    return obj
  }

  //点击确定
  const handleConfirm = debounce(async (): Promise<void> => {
    let formObj = await formatParam()
    await formRef.value?.validate()
    const isUploadingList = [
      videoUploadRef.value?.getIsUploading(),
      docUploadRef.value?.getIsUploading(),
      attachmentsUploadRef.value?.getIsUploading()
    ]
    console.log(isUploadingList, 'isUploadingList')
    if (isUploadingList.includes(true)) {
      message.warning('文件正在上传中')
      return
    }
    if (cardType) {
      addCourseForm(formObj, { isAddUid: true })
    } else {
      editCourseForm(formObj, { isAddUid: true })
    }
  })

  onMounted(() => {
    init()
  })
  const init = async () => {
    await getDataLabel({ type: 'course_category' })
    await getDataLabel({ type: 'course_level' })
    if (!cardType) {
      detailsCourseForm()
    }
  }
  const getPopupContainer = (triggerNode: any) => {
    return triggerNode.parentNode
  }
  // // 退出或者跳转时
  // router.beforeEach((to, from, next) => {
  //   // next(false)
  //   console.log('正在推出')
  // })
</script>
<style lang="less" scoped>
  :deep(.ant-form-item) {
    margin-bottom: 40px;
  }

  .upload-card {
    margin-left: 120px;
    border: 1px solid @border1;
    border-radius: 10px;

    .upload-header {
      display: flex;
      align-items: center;
      padding: 8px 24px;
      gap: 12px;
      border-bottom: 1px solid var(--mask-1, rgba(0, 0, 0, 0.05));

      .icon-class {
        width: 20px;
        height: 20px;
        color: @primary1;
      }

      .upload-header-title {
        font-size: 14px;
        font-family: 'Noto Sans SC';
        color: @text01;
        font-style: normal;
        font-weight: 700;
        line-height: 22px;
      }
    }

    .upload-box {
      padding: 24px;
    }
  }

  .w440 {
    width: 440px;
  }

  .w312 {
    width: 312px;
  }

  .upload-image-info {
    justify-content: flex-end;
    margin-top: auto;
    width: 148px;
    font-size: 12px;
    text-align: right;
    text-align: end;
    color: rgba(25, 25, 48, 0.45);
    line-height: 20px;
  }

  .upload-item {
    :deep(.ant-form-item-explain-error) {
      margin-left: 120px;
    }
  }
</style>
